#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int Create_socket(int port)
{
	int ret = 0;
	int sock_fd = -1;
	/*创建套接字*/
	sock_fd = socket(AF_INET, SOCK_STREAM, 0);
	if(-1 == sock_fd)
	{
		printf("socket faild,err:%s\n", strerror(errno));
		return -1;
	}
	//设置端口复用
	//int opt = 1;
	//setsockopt(sock_fd,SOL_SOCKET,SO_REUSEADDR,(const void *) &opt,sizeof(opt));
	/*绑定地址*/
	struct sockaddr_in sock_addr;
	sock_addr.sin_family = AF_INET;
	sock_addr.sin_port = htons(port);
	sock_addr.sin_addr.s_addr = INADDR_ANY;
	ret = bind(sock_fd, (struct sockaddr*)&sock_addr, sizeof(struct sockaddr_in));
	if(ret < 0)
	{
		printf("bind Error:%m\n");
		close(sock_fd);
		sock_fd = -1;
		return -1;
	}
	return sock_fd;
}
int Do_Connect_socket(int sock_fd,char* srv_ip,int srv_port)
{
	//连接server端的ip和port
	struct sockaddr_in sock_server;
	sock_server.sin_port = htons(srv_port);
	sock_server.sin_addr.s_addr = inet_addr(srv_ip);
	sock_server.sin_family = PF_INET;
	memset(sock_server.sin_zero,0,8);
	int ret = connect(sock_fd,(struct sockaddr *)&sock_server,sizeof(struct sockaddr));
	if(-1 == ret)
	{
		close(sock_fd);
		printf(" connect faild,err:%s\n", strerror(errno));
		return -1;
	}

	return ret;
}

void sig_chld(int signo)
{
	pid_t pid;
	int stat;
	while((pid = waitpid(-1,&stat,WNOHANG)) > 0)
		printf("child %d terminated\n",pid);

	return;
}

void print_addr(int connfd)
{
	struct sockaddr_in srvaddr,peeraddr;
	int srvlen,peerlen;

	getsockname(connfd,(struct sockaddr*)&srvaddr,&srvlen);
	printf("srvaddr:%s\n",inet_ntoa(srvaddr.sin_addr));
	printf("srvport:%d\n",ntohs(srvaddr.sin_port));

	getpeername(connfd,(struct sockaddr*)&peeraddr,&peerlen);
	printf("peeraddr:%s\n",inet_ntoa(peeraddr.sin_addr));
	printf("peerport:%d\n",ntohs(peeraddr.sin_port));
}
int main()
{
	int fd=0,connfd;
	pid_t pid;
	int clilen,srvlen,peerlen;
	struct sockaddr_in srvaddr,cliaddr,peeraddr;
	peerlen = srvlen = clilen = sizeof(cliaddr);
	fd=Create_socket(55560);
	listen(fd,5);
	signal(SIGCHLD,sig_chld);
	//connfd = accept(fd,(struct sockaddr*)&cliaddr,&clilen);
	for(;;){
		connfd = accept(fd,(struct sockaddr*)NULL,NULL);
		if(connfd < 0){
			if(errno == EINTR)
				continue;
			else
				printf("accept error:%m\n");
		}
		if((pid = fork()) == 0){
			close(fd);
			//print_addr(connfd);
			getsockname(connfd,(struct sockaddr*)&srvaddr,&srvlen);
			printf("srvaddr:%s\n",inet_ntoa(srvaddr.sin_addr));
			printf("srvport:%d\n",ntohs(srvaddr.sin_port));

			getpeername(connfd,(struct sockaddr*)&peeraddr,&peerlen);
			printf("peeraddr:%s\n",inet_ntoa(peeraddr.sin_addr));
			printf("peerport:%d\n",ntohs(peeraddr.sin_port));
			exit(0);
		}
		else{
			close(connfd);
		}
	}
	return 0;
}
